package other.system.client.sap;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEvent;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEventRequest;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEventResponse;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.system.client.apitool.SAPClientUtils;
import other.system.client.util.*;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description 推送开票数据到SAP
 * @Author 黎炎松
 * 2024-07-18 09:32
 */
@RestApi(baseUrl = "/xsy/sap")
public class PushInvoiceToSap implements ApprovalEvent, FutureTask {
    private static XoqlService xoqlService = XoqlService.instance();
    private static final Logger logger = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "推送开票数据到SAP ==> ";

    @Override
    public ApprovalEventResponse execute(ApprovalEventRequest request) {
        logger.info(LOGGER_MSG + "审批完成触发开始");
        logger.info("ObjectApiKey:" + request.getEntityApiKey() + " , DataId:" + request.getDataId());

        // 执行异步任务
        try {
            // doPushInvoiceToSap(request.getDataId());
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), String.valueOf(request.getDataId()));
            logger.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (AsyncTaskException e) {
            throw new RuntimeException(e);
        }

        ApprovalEventResponse response = new ApprovalEventResponse();
        response.setSuccess(true);
        response.setMsg("success");
        return response;
    }

    /**
     * 异步执行事件
     * @param s
     * @throws ScriptBusinessException
     */
    @Override
    public void execute(String s) throws ScriptBusinessException {
        logger.info(LOGGER_MSG + "******开始执行异步任务");
        doPushInvoiceToSap(Long.valueOf(s));
        logger.info(LOGGER_MSG + "******执行异步任务结束");
    }

    /**
     * 手动推送客户数据
     * @param invoiceId
     * @return
     */
    @RestMapping(value = "/pushInvoiceToSap", method = RequestMethod.POST)
    public String doOpt(@RestQueryParam(name = "id") Long invoiceId) throws ApiEntityServiceException {
        logger.info(LOGGER_MSG + "执行了按钮事件 = " + invoiceId);
        return doPushInvoiceToSap(invoiceId);
    }


    public static void main(String[] args) throws ApiEntityServiceException {
        new PushInvoiceToSap().doPushInvoiceToSap(3968410631150172L);
    }

    /**
     * 推送开票数据到SAP (需要使用异步，否则会出现链接sap超过15秒导致超时的情况)
     * @param invoiceId
     * @return
     */
    public String doPushInvoiceToSap(Long invoiceId) {
        try {

            // 获取开票数据
            logger.info(LOGGER_MSG + "处理开始: " + invoiceId);
            String sql = "select id,invoiceID__c,companyName__c,customerName__c.accountName customerName,customerName__c.sapCustomerCode__c sapCustomerCode, " +
                    "clientName__c.accountName clientName,customItem19__c,ratepaying__c,totalAmount__c,advanceAmount__c,projectNumber__c,applicationDate__c " +
                    "from invoice__c where id = " + invoiceId;
            List<JSONObject> invoiceList = xoqlService.query(sql, true).getRecords();
            if (invoiceList.size() <= 0) {
                logger.error(LOGGER_MSG + "查询开票数据异常");
                return TfReturnMsgTools.getFailResult("查询开票数据异常");
            }

            // 获取主表数据
            JSONObject invoice = invoiceList.get(0);
            String sapCustomerCode = invoice.getString("sapCustomerCode");
            if (StringUtils.isBlank(sapCustomerCode)) {
                logger.error(LOGGER_MSG + "当前客户'SAP客户编码'不可为空");
                return TfReturnMsgTools.getFailResult("当前客户'SAP客户编码'不可为空");
            }

            // 开票日期
            String applicationDateStr = "";
            Long applicationDate = invoice.getLong("applicationDate__c");
            if (applicationDate != null) {
                applicationDateStr = HCDateUtils.longToString(applicationDate, HCDateUtils.FORMAT);
            }

            // 获取选项集，发票种类需要推送数值 apiKey
            JSONObject invoiceDesc = ComUtils.getEntityDesc("invoice__c");
            Map<String, String> invoicePicks = ComUtils.getMapsFromDescribeJson(invoiceDesc, "customItem19__c", "label", "apiKey");

            // 获取开票明细 amountTZ__c receivableDetail__c.name receivablesDetailName,
            sql = "select id,name,orderNumber__c.po orderPo,orderNumber__c.amountTZ__c amountTZ,billReceivable__c.name billReceivableName," +
                    " booking__c.name bookingName,bookingType__c,invoiceName__c,customItem12__c,quantity__c,taxRat__c,invoiceRemarks__c,specificationModel__c,invoiceDetails__c" +
                    " from invoiceDetail__c where invoice__c = " + invoiceId;
            List<JSONObject> invoiceDetailList = xoqlService.query(sql, true).getRecords();
            if (invoiceDetailList.size() <= 0) {
                logger.error(LOGGER_MSG + "查询开票明细数据为空");
                return TfReturnMsgTools.getFailResult("查询开票明细数据为空");
            }

            JSONArray sendData = new JSONArray();
            for (JSONObject invoiceDetail : invoiceDetailList) {
                JSONObject formData = new JSONObject();
                formData.put("INVOICEID__C", invoice.getString("invoiceID__c")); // 开票id
                formData.put("NAME", invoiceDetail.getString("name")); // 开票明细编码
                formData.put("COMPANYNAME__C", invoice.getString("companyName__c")); // 我司公司主体
                formData.put("ORDERNUMBER__C", invoiceDetail.getString("orderPo")); // 合同号
                formData.put("BILLRECEIVABLE__C", invoiceDetail.getString("billReceivableName")); // 应收单号
                formData.put("RECEIVABLESDETAIL__C", invoiceDetail.getString("receivablesDetailName")); //   应收明细
                formData.put("BOOKING__C", invoiceDetail.getString("bookingName")); // booking
                formData.put("BOOKINGTYPE__C", getOptionStr(invoiceDetail.getJSONArray("bookingType__c"))); // booking类型
                formData.put("CUSTOMERNAME__C", invoice.getString("customerName")); // 客户名称（开票单位）
                formData.put("SAPCUSTOMERCODE__C", sapCustomerCode); // 客户编码
                formData.put("CLIENTNAME__C", invoice.getString("clientName")); // 签约客户名称

                // 发票种类
                String customItem19 = getOptionStr(invoice.getJSONArray("customItem19__c"));
                if (StringUtils.isNotBlank(customItem19)) {
                    formData.put("CUSTOMITEM19__C", invoicePicks.get(customItem19));
                }

                formData.put("RATEPAYING__C", invoice.getString("ratepaying__c")); // 纳税登记号(客户）
                formData.put("CONTRACTAMOUNTINTAX", formatAmount(invoiceDetail.getDouble("amountTZ"))); // 合同金额(含税)
                formData.put("TOTALAMOUNT__C", formatAmount(invoice.getDouble("totalAmount__c"))); // 申请开票金额（含税）
                formData.put("ADVANCEAMOUNT__C", formatAmount(invoice.getDouble("advanceAmount__c"))); // 预收金额
                formData.put("INVOICENAME__C", invoiceDetail.getString("invoiceName__c")); // 开票商品名称
                formData.put("PROJECTNUMBER__C", invoice.getString("projectNumber__c")); // 项目号
                formData.put("PRODUCT__C", invoiceDetail.getString("specificationModel__c")); // 规格型号
                formData.put("CUSTOMITEM12__C", invoiceDetail.getString("customItem12__c")); // 单位
                formData.put("QUANTITY__C", invoiceDetail.getString("quantity__c")); // 数量
                formData.put("INVOICEDETAILS__C", formatAmount(invoiceDetail.getDouble("invoiceDetails__c"))); // 开票明细金额

                // 税率 6% 传 0.06
                String taxRate = getOptionStr(invoiceDetail.getJSONArray("taxRat__c"));
                if (StringUtils.isNotBlank(taxRate)) {
                    taxRate = taxRate.replace("%", "");
                    String taxRateVal = BigDecimal.valueOf(Long.parseLong(taxRate)).divide(BigDecimal.valueOf(100)).toString();
                    formData.put("TAXRATE__C", taxRateVal);
                }

                formData.put("APPLICATIONDATE__C", applicationDateStr); // 申请日期
                formData.put("INVOICEREMARKS", invoiceDetail.getString("invoiceRemarks__c")); // 开票备注
                sendData.add(formData);
            }
            // 拼接发送参数

            JSONObject reqBody = new JSONObject();
            reqBody.put("I_JKLX", "JS");
            reqBody.put("IT_KPXXJS", sendData);
            logger.info(LOGGER_MSG + "发送的数据: " + reqBody);


            // 推送到SAP
            ResultBody resultBody = SAPClientUtils.sendPost(reqBody, SAPClientUtils.INVOICE_URL, "");
            logger.debug(LOGGER_MSG + "resultBody:" + resultBody);
            if (!Objects.equals(resultBody.getCode(), "200")) {
                logger.error(LOGGER_MSG + "推送异常: " + resultBody.getMessage());
                return TfReturnMsgTools.getFailResult("推送异常:" + resultBody.getMessage());
            }

            logger.info(LOGGER_MSG + "推送成功");
            return TfReturnMsgTools.getSuccessResult("推送成功");
        } catch (Exception e) {
            logger.error(LOGGER_MSG + "处理异常: " + e.getMessage());
            return TfReturnMsgTools.getFailResult("推送异常:" + e.getMessage());
        }
    }

    /**
     * 获取选项的字符串值
     * @param optionArr
     * @return
     */
    public String getOptionStr(JSONArray optionArr) {
        String optStr = "";
        if (optionArr != null && optionArr.size() > 0) {
            optStr = optionArr.stream().map(v -> v.toString()).collect(Collectors.joining(","));
        }
        return optStr;
    }

    public String formatAmount(Double amount) {
        String formatAmount = "";
        if (amount != null) {
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            formatAmount = decimalFormat.format(amount);
        }
        System.out.println("formatAmount = " + formatAmount);
        return formatAmount;
    }



}
